﻿' ------------------------------------------------------------------------------
' The CreateWebPage method in this module creates an html file that
' displays a map using Virtual Earth with pushpins at each photo's
' location.
'
' It creates the page using a template file whose path is stored in
' My.Settings.RTS_VirtualEarthHtmlTemplate. The template is read line by
' line. Most lines are written directly to the output file. Certain
' lines with special comments are replaced with javascript code that is
' generated by this method.
'
' The web page contains javascript functions for loading photos onto the
' map as pushpins. The BeginAddingPhotos, AddPhoto, and EndAddingPhotos
' javascript functions are called the LoadPhotos() method. AddPhoto is
' called once for each photo. Event handlers are set up so when the user
' clicks or double-clicks on a pushpin, the shape id is returned to this
' application which then updates the application's state.

' The AddPhoto javascript function is called for each photo after the
' page has been loaded. It creates a Virtual Earth VEShape pushpin
' object for each photo and adds these to the map. The pushpins are
' located at the photos' locations, the title contains some infomration
' about the photos, and the description contains html code to display
' the image thumbnail. The thumbnails are stored in temporary
' files. VEShape allows for setting a URL to an image what will be
' automatically displayed in the pushpin's balloon, but this image will
' not load using the file: protocol. Since the thumbnails are stored on
' a local drive, they can only be accessed using this protocol in the
' absense of a web server running on the local machine.
' ------------------------------------------------------------------------------
' This file is part of the SQL Server 2008 Technology Demonstration. This
' application was designed and coded by Eric Weitzman, LandTime Inc, for
' Microsoft Corporation. Contact Ed Katibah at Microsoft about this demo.
' Copyright © 2008 Microsoft Corporation. All rights reserved.
' ------------------------------------------------------------------------------

Public Enum EnumIcon
    eDefault
    eRed
    eBlue
End Enum

Public Module VirtualEarthMap

    Public Photos As Dictionary(Of String, DataRow)
    Public Icon As EnumIcon = EnumIcon.eDefault

    Public Sub LoadPhotos(ByVal dt As DataTable, ByVal doc As HtmlDocument)
        'doc.InvokeScript("test", New String() {"Message from main application: Hello!"})
        doc.InvokeScript("BeginAddingPhotos")

        Photos = New Dictionary(Of String, DataRow)
        If Icon = EnumIcon.eDefault Then
            doc.InvokeScript("SetIcon", New Object() {Nothing})
        Else
            Dim iconsource As String = ""
            Select Case Icon
                Case EnumIcon.eBlue : iconsource = My.Settings.RTS_BlueIcon
                Case EnumIcon.eRed : iconsource = My.Settings.RTS_RedIcon
            End Select
            Dim icondest As String = MiscellaneousUtils.TempFileName(System.IO.Path.GetExtension(iconsource))
            System.IO.File.Copy(iconsource, icondest)
            Dim iconurl As String = "file:///" & icondest.Replace("\"c, "/"c)
            doc.InvokeScript("SetIcon", New Object() {iconurl})
        End If

        Dim pinid As Integer = 0
        For Each dr As DataRow In dt.Rows
            Dim location As SqlGeography = CType(dr.Item("Location"), SqlGeography)
            If Not location.IsNull Then

                Dim filename As String = CType(dr.Item("Filename"), String)
                Dim dto As DateTimeOffset = CType(dr.Item("DateTimeOffset"), DateTimeOffset)
                Dim time As String = dto.ToString()

                Dim thumbfile As String = MiscellaneousUtils.TempFileName(".jpg")
                Dim thumburl As String = "file:///" & thumbfile.Replace("\"c, "/"c)
                Dim x As Object = dr.Item("Thumbnail")
                SaveImageBytesToFile(CType(dr.Item("Thumbnail"), Byte()), thumbfile)

                Dim lat As Double = location.Lat.Value
                Dim lon As Double = location.Long.Value

                pinid += 1
                Dim title As String = filename & " (Pin" & pinid & ")"
                Dim description As String = time

                'javascript: function AddPhoto(lat, long, title, description, thumbnailurl)
                Dim shapeid As String = CType(doc.InvokeScript("AddPhoto", New Object() {lat, lon, title, description, thumburl}), String)
                Photos.Add(shapeid, dr)

            End If
        Next
        doc.InvokeScript("EndAddingPhotos")
    End Sub

    Public Sub PanTo(ByVal latitude As Double, ByVal longitude As Double, ByVal doc As HtmlDocument)
        doc.InvokeScript("PanTo", New Object() {latitude, longitude})
    End Sub

    Public Function CreateWebPage(ByVal dt As DataTable, _
                                  ByVal showcontrols As Boolean, _
                                  Optional ByVal mappixelwidth As Integer = 0, _
                                  Optional ByVal mappixelheight As Integer = 0) As String
        'Trace.WriteLine("CreateWebPage: " & mappixelwidth & " x " & mappixelheight)

        Dim ifile As String = IO.Path.Combine(IO.Directory.GetCurrentDirectory(), My.Settings.RTS_VirtualEarthHtmlTemplate)
        Dim ofile As String = MiscellaneousUtils.TempFileName(".html")

        Dim istrm As New System.IO.StreamReader(ifile)
        Dim ostrm As New System.IO.StreamWriter(ofile)

        Dim line As String = istrm.ReadLine
        While Not istrm.EndOfStream
            ostrm.WriteLine(line)

            If line.Trim = "<!-- AddMapDiv -->" Then

                Dim pxwidth As String = "auto"
                If mappixelwidth <> 0 Then pxwidth = String.Format("{0}px", mappixelwidth - 20)
                Dim pxheight As String = "auto"
                If mappixelheight <> 0 Then pxheight = String.Format("{0}px", mappixelheight - 30)
                ostrm.WriteLine("<div id='MapDiv' style='position:relative; width:" & pxwidth _
                                & "; height:" & pxheight & ";'></div>")

            ElseIf line.Trim = "// WriteBoilerplate" Then

                ostrm.WriteLine("        function WriteBoilerplate() {")
                ostrm.WriteLine("            // this code is not in use in this build")
                ostrm.WriteLine("            //alert('writing boilerplate');")
                ostrm.WriteLine("            //var div = document.getElementById('Boilerplate');")
                ostrm.WriteLine("            //var br = document.createElement('br');")
                ostrm.WriteLine("            //div.appendChild(br);")
                ostrm.WriteLine("            //var text = document.createTextNode('(" & dt.Rows.Count & ") " & ofile.Replace("\", "\\") & "');")
                ostrm.WriteLine("            //div.appendChild(text);")
                ostrm.WriteLine("            //var br2 = document.createElement('br');")
                ostrm.WriteLine("            //div.appendChild(br2);")
                ostrm.WriteLine("        }")

            ElseIf line.Trim = "// SetupMap" Then

                ostrm.WriteLine("        function SetupMap() {")
                ostrm.WriteLine("            map = new VEMap('MapDiv');")
                ostrm.WriteLine("            map.LoadMap();")
                If showcontrols Then
                    ostrm.WriteLine("            map.ShowDashboard();")
                Else
                    ostrm.WriteLine("            map.HideDashboard();")
                End If
                ostrm.WriteLine("            map.SetMapMode(VEMapMode.Mode2D);")
                ostrm.WriteLine("            map.AttachEvent('onclick', OnPhotoClickHostCallback);")
                ostrm.WriteLine("            map.AttachEvent('ondoubleclick', OnPhotoDoubleClickHostCallback);")
                ostrm.WriteLine("        }")

            End If
            line = istrm.ReadLine
        End While

        istrm.Close()
        ostrm.Close()

        Return ofile

    End Function

#If False Then

    Public Function CreateWebPageOLD(ByVal dt As DataTable, _
                                  ByVal showcontrols As Boolean, _
                                  Optional ByVal mappixelwidth As Integer = 0, _
                                  Optional ByVal mappixelheight As Integer = 0) As String

        Dim ifile As String = IO.Path.Combine(IO.Directory.GetCurrentDirectory(), My.Settings.RTS_VirtualEarthHtmlTemplate)
        Dim ofile As String = MiscellaneousUtils.TempFileName(".html")

        Dim istrm As New System.IO.StreamReader(ifile)
        Dim ostrm As New System.IO.StreamWriter(ofile)

        Dim line As String = istrm.ReadLine
        While Not istrm.EndOfStream
            ostrm.WriteLine(line)

            If line.Trim = "// Boilerplate" Then
                'ostrm.WriteLine("document.write('Loading' + '" & ofile & "' + '<br>')")

            ElseIf line.Trim = "<!-- AddMapDiv -->" Then
                Dim pxwidth As String = "auto"
                If mappixelwidth <> 0 Then pxwidth = String.Format("{0}px", mappixelwidth - 40)
                Dim pxheight As String = "auto"
                If mappixelheight <> 0 Then pxheight = String.Format("{0}px", mappixelheight - 30)
                ostrm.WriteLine("<div id='MapDiv' style='position:relative; width:" & pxwidth _
                                & "; height:" & pxheight & ";'></div>")

            ElseIf line.Trim = "// WriteBoilerplate" Then
                ostrm.WriteLine("      function WriteBoilerplate()")
                ostrm.WriteLine("      {")
                ostrm.WriteLine("        //alert('writing boilerplate');")
                ostrm.WriteLine("        var div = document.getElementById('Boilerplate');")
                ostrm.WriteLine("        var br = document.createElement('br');")
                ostrm.WriteLine("        div.appendChild(br);")
                ostrm.WriteLine("        var text = document.createTextNode('(" & _
                                         dt.Rows.Count & ") " & ofile.Replace("\", "\\") & "');")
                ostrm.WriteLine("        div.appendChild(text);")
                ostrm.WriteLine("        var br2 = document.createElement('br');")
                ostrm.WriteLine("        div.appendChild(br2);")
                ostrm.WriteLine("      }")

            ElseIf line.Trim = "// LoadPins" Then
                ostrm.WriteLine("      function LoadPins()")
                ostrm.WriteLine("      {")
                ostrm.WriteLine("        //alert('loading pins');")

                If showcontrols Then
                    ostrm.WriteLine("        map.ShowDashboard();")
                Else
                    ostrm.WriteLine("        map.HideDashboard();")
                End If

                ostrm.WriteLine("")
                If dt.Rows.Count <> 0 Then _
                    ostrm.WriteLine("        var points = new Array();")

                Dim pinid As Integer = 0
                Try
                    For Each dr As DataRow In dt.Rows
                        Dim location As SqlGeography = CType(dr.Item("Location"), SqlGeography)
                        If Not location.IsNull Then

                            Dim filename As String = CType(dr.Item("Filename"), String)
                            Dim dto As DateTimeOffset = CType(dr.Item("DateTimeOffset"), DateTimeOffset)
                            Dim time As String = dto.ToString()

                            Dim thumbfile As String = MiscellaneousUtils.TempFileName(".jpg")
                            Dim thumburl As String = "file:///" & thumbfile.Replace("\"c, "/"c)
                            Dim x As Object = dr.Item("Thumbnail")
                            SaveImageBytesToFile(CType(dr.Item("Thumbnail"), Byte()), thumbfile)

                            Dim lat As Double = location.Lat.Value
                            Dim lon As Double = location.Long.Value
                            ostrm.WriteLine("          var pnt = new VELatLong(" & lat & ", " & lon & ");")

                            pinid += 1
                            ostrm.WriteLine("          points[" & pinid - 1 & "] = pnt;")
                            ostrm.WriteLine("          var shape = new VEShape(VEShapeType.Pushpin, pnt);")
                            ostrm.WriteLine("          shape.SetTitle('<center>" & filename & " (Pin" & pinid & ")</center>');")
                            'ostrm.WriteLine("          shape.SetPhotoURL('" & thumburl & "');")
                            'ostrm.WriteLine("          shape.SetDescription('<center>" & time & "<br><img width=""80"" height=""80"" src=""" & thumburl & """></center>');")
                            ostrm.WriteLine("          shape.SetDescription('<center>" & time & "<br><img src=""" & thumburl & """></center>');")
                            ostrm.WriteLine("          map.AddShape(shape);")
                        End If
                    Next
                    If pinid <> 0 Then _
                        ostrm.WriteLine("          map.SetMapView(points);")
                    ostrm.WriteLine("      }")

                    Trace.WriteLine("created pins for " & pinid & " photo(s)")
                    If pinid <> dt.Rows.Count Then Trace.WriteLine((dt.Rows.Count - pinid) & " photo(s) have NULL locations")

                Catch ex As Exception
                    ReportException(ex)
                End Try
            End If
            line = istrm.ReadLine
        End While

        istrm.Close()
        ostrm.Close()

        Return ofile

    End Function
#End If

End Module
